<?php

class Workset_Sphinx {

    protected static $_defaultOptions = null;

    protected $_adapter = null;

    protected $_adapterPrefixPaths = array(
        'Workset_Sphinx_Adapter' => 'Workset/Sphinx/Adapter'
    );

    public static function setDefaultOptions($options) {
        if ($options instanceof Zend_Config) {
            $options = $options->toArray();

        } elseif (!is_array($options)) {
            throw new Zend_Exception('Options type must be an array or instance of Zend_Config');
        }

        self::$_defaultOptions = $options;
    }

    public static function getDefaultOptions() {
        return null !== self::$_defaultOptions ? self::$_defaultOptions : array();
    }

    public function __construct($adapter = null, $options = null) {
         if (null !== $adapter) {
             $this->setAdapter($adapter, $options);
         }
    }

    public function __call($method, $args) {
        return $this->getAdapter()->{$method}($args);
    }

    public function query(Workset_Sphinx_Query_Interface $query) {
        return $this->getAdapter()->query($query);
    }

    public function setOptions($options) {
        if ($options instanceof Zend_Config) {
           $options = $options->toArray();
        }

        if (isset($options['adapter'])) {
            $adapter = $options['adapter'];
            unset($options['adapter']);

            $this->setAdapter($adapter, $options);
        } else {
            $this->getAdapter()->setOptions($options);
        }
    }

    public function setAdapter($adapter, $options = null) {

         if (null !== $options && null !== self::$_defaultOptions) {
             if ($options instanceof Zend_Config) {
                 $options = $options->toArray();
             } else {
                 $options = (array)$options;
             }

             $options = arrayMerge(self::$_defaultOptions, $options);
         }

         if ($adapter instanceof Workset_Sphinx_Adapter_Interface) {
             $adapter->setOptions($options);

         } elseif (is_string($adapter)) {
             if (class_exists($adapter)) {
                 $adapter = new $adapter();
                 $adapter->setOptions($options);
             } else {
                 $name = ucfirst($adapter);

                 foreach ($this->_adapterPrefixPaths as $prefix => $path) {
                     $class = $prefix . '_' . $name;
                     if (!class_exists($class)) {
                         Zend_Loader::loadClass($class, $path);
                     }
                     $adapter = new $class();
                     $adapter->setOptions($options);
                     break;
                 }
             }
         }

        $this->_adapter = $adapter;
    }

    public function getAdapter() {
        return $this->_adapter;
    }

    public function addAdapterPrefixPath($prefix, $path = null) {
        if (is_array($prefix)) {
            $path = current($prefix);
            $prefix = key($prefix);
        }

        if (is_string($prefix) && is_string($path)) {
            $path = trim($path, '\/');
            $prefix = trim($prefix, '_');

            if (!isset($this->_adapterPrefixPaths[$prefix])) {
               $this->_adapterPrefixPaths[$prefix] = $path;
            }
        } else {
            throw new Zend_Exception('Invalid prefix or path format');
        }

    }

}